package com.xbdun.comweb.bmp.freemark;

import java.io.IOException;
import java.io.Writer;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.util.NodeList;

import com.xbdun.common.enums.UserRolesEnums;
import com.xbdun.common.exceptions.BizException;
import com.xbdun.comweb.bmp.constants.SessionConstant;
import com.xbdun.comweb.bmp.session.CurrentUserInfo;
import com.xbdun.comweb.bmp.util.UserInfoUtil;

import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
import lombok.extern.slf4j.Slf4j;

/**
 * 用法，主要是 token
<@AuthBtn>
	<button type="button" class="btn btn-primary" id="btn_100101103100" token="100101103100">新增</button>
    <button type="button" class="btn btn-success" id="btn_100101103101" token="100101103101">修改</button>
    <button type="button" class="btn btn-danger" id="btn_100101103102"	token="100101103102">删除</button>
    <button type="button" class="btn btn-primary" id="btn_100101103103"	token="100101103103">检索</button>
	<button type="button" class="btn btn-info" id="btn_100101103104"	token="100101103104">详情</button>
	<button type="button" class="btn btn-warning" id="btn_100101103108"	token="100101103108">生效/未生效</button>
	<button type="button" class="btn btn-danger" id="btn_100101103109"	token="100101103109">启用/停用</button>
	<button type="button" class="btn btn-warning" id="btn_100101103105"	token="100101103105">设置部门</button>
	<button type="button" class="btn btn-warning" id="btn_100101103106"	token="00101103106">特殊权限设置</button>
	<button type="button" class="btn btn-info" id="btn_100101103107"	token="100101103107">查看权限</button>
</@AuthBtn>
@ClassName: AuthBtnDirective
* @Description: TODO(这里用一句话描述这个类的作用)
* @author zhanggt 360730440@qq.com
* @date 2017年5月11日 下午7:25:12
 */
@Slf4j
public class AuthBtnDirective implements TemplateDirectiveModel {
	public void execute(Environment env, @SuppressWarnings("rawtypes") Map params, TemplateModel[] loopVars,TemplateDirectiveBody body) throws TemplateException, IOException {
    	AuthFilterWriter authWrite = null;
    	// 获取用户登录信息
        CurrentUserInfo userInfo = (CurrentUserInfo)UserInfoUtil.getCurrentRequest().getAttribute(SessionConstant.REQUEST_USER_SESSION);
        if(null==userInfo){
        	userInfo =  UserInfoUtil.getCurrentUserInfo(UserInfoUtil.getCurrentRequest());
        }
        if (body != null&&userInfo != null) {
        	authWrite = new AuthFilterWriter(userInfo,env.getOut());
            body.render(authWrite);
        } else {
            env.getOut().write("");
        }
        //释放资源
        authWrite = null;
    }
    /**
    * @param userInfo 
     * @Title: getAutHtml
    * @Description: 输出HTML标签
    * @param ctrlId
    * @param html
    * @return    设定文件
    * @return String    返回类型
     */
    private String getAutHtml(CurrentUserInfo userInfo, String html) {
    	StringBuilder sbHtml = new StringBuilder();
        Parser parser = Parser.createParser(html, "UTF-8");
        NodeFilter filter = new HasAttributeFilter("token");
        try {
        	//获取当前用户的有效权限
        	String userAuth = UserInfoUtil.getIUserAuth().getUserAuth(UserInfoUtil.getClient(UserInfoUtil.getCurrentRequest(),userInfo));
            NodeList nodes = parser.extractAllNodesThatMatch(filter);
            for(int i=0;i<nodes.size()&&null!=userAuth;i++){
            	Tag node = (Tag)nodes.elementAt(i);
            	String _token = StringUtils.defaultIfBlank(node.getAttribute("token"),"");
            	//不是平台管理员
            	if(!UserRolesEnums.isXbdAdmin(userInfo.getRoleId())){
            		//当前访问的路径地址是否为当前平台
            		if(!_token.startsWith(userInfo.getPlatCode()+"")){
            			throw BizException.POWER_FAIL.newInstance("您访问的路径并非为当前系统定义路径["+_token+"]");
            		}
            		//如果是超级管理员
            		if(UserRolesEnums.isSupperAdmin(userInfo.getRoleId())){
            			//获取当前机构权限
            			String currentOrgAuth = UserInfoUtil.getIUserAuth().getCurrentOrgAuth(userInfo.getOrgCode(), userInfo.getPlatCode());
            			if(null!=currentOrgAuth&&currentOrgAuth.indexOf(","+_token+",")!=-1){
            				//构造按钮
                			sysAuthButton(sbHtml,node,_token);
            			}
            		}else{
            			//不是平台管理，判断当前用户是否存在权限
            			if(userAuth.indexOf(","+_token+",")!=-1){
                			//构造按钮
                			sysAuthButton(sbHtml,node,_token);
                		}
            		}
            	}else{
            		//构造按钮
            		sysAuthButton(sbHtml,node,_token);
            	}
            	//释放内存指针
            	_token = null;
            }
            //释放资源
            userAuth = null;
        } catch (Exception e) {
            log.error("权限判断按钮权限异常",e);
            
        }
        return sbHtml.toString();
    }
    //自定义权限按钮
    private class AuthFilterWriter extends Writer {
        private final Writer out;
        private CurrentUserInfo userInfo;
        AuthFilterWriter(CurrentUserInfo userInfo, Writer out){
            this.out = out;
            this.userInfo = userInfo;
        }
        public void close() throws IOException {
            out.close();
        }
        public void flush() throws IOException {
            out.flush();
        }
        public void write(char[] cbuf, int off, int len) throws IOException {
            String noAuthHtml = new String(cbuf);
            log.info("授权前的html------ >" + noAuthHtml);
            // 通过解析标签中html内容，接口后台的权限配置数据过滤出授权后台html内容
            String rtnHtml = getAutHtml(userInfo,noAuthHtml);
            log.info("授权后的html------ >" + rtnHtml);
            out.write(rtnHtml.toCharArray());
        }
    }
    
    //构建Button
    private void sysAuthButton(StringBuilder sbHtml,Tag node,String _token){
		//获取系统缓存对象的菜单描述
		String sysPlatAuth = UserInfoUtil.getIUserAuth().getSysPlatAuth(_token);
		if(null!=sysPlatAuth){
			String[] split = sysPlatAuth.split("\\^");
			node.setAttribute("title",split[1]);//按钮描述
			sbHtml.append(node.toHtml());//按钮前部分
			sbHtml.append(split[0]);//按钮文本
		}else{
			sbHtml.append(node.toHtml());//按钮前部分
		}
		//按钮末尾部分
		sbHtml.append("</button>");	
    }
}
